#ifndef __WIZ_VFS_DIRTREE_HPP__SHANHAOBO_19800429__
#define __WIZ_VFS_DIRTREE_HPP__SHANHAOBO_19800429__

#include "../Core/File/WizFileDirTree.hpp"

namespace Wiz
{
    namespace VFS
    {
        namespace DirTree
        {
            template<class DerivedT>
            struct Type : public ::Wiz::File::DirTree::Type<DerivedT>
            {
                typedef ::Wiz::File::DirTree::Type<DerivedT> tSuper;
                //////////////////////////////////////////////////////////////////////////
                virtual ::Wiz::Void::Type Serialize(::Wiz::Archive::InOut IOArchive)
                {
                    /// NAME
                    IOArchive && (this->m_Name);

                    /// ISFILE
                    IOArchive && (this->m_IsFile);

                    /// FirstChildPtr
                    IOArchive && (::Wiz::Byte::Ptr&)(this->m_FirstChildPtr);

                    /// NextSiblingPtr
                    IOArchive && (::Wiz::Byte::Ptr&)(this->m_NextSiblingPtr);

                    /// ParentPtr
                    IOArchive && (::Wiz::Byte::Ptr&)(this->m_ParentPtr);

                    /// External
                    IOArchive && this->m_ExternalSize;
                }

                virtual ::Wiz::Void::Type SerializeExternal(::Wiz::Archive::InOut IOArchive)
                {
                    
                }

                ::Wiz::Bool::Type Read(::Wiz::Archive::InOut InArchive)
                {
                    typedef ::Wiz::Map::Type<tDerivedPtr, tDerivedPtr>    tMap;
                    tMap                        m_Map;

                    ::Wiz::UInt32::Type         m_Count = 0;
                    InArchive && m_Count;
                    ::Wiz::UInt32::Type i;
                    for (i = 0; i < m_Count; i++)
                    {
                        tDerivedPtr MePtr = WIZ_NULLPTR;

                        if (i == 0)
                        {
                            MePtr = ::Wiz::Cast::Dynamic<tDerivedPtr>(this);
                        }
                        else
                        {
                            MePtr = new tDerived(::Wiz::UTF8::String::Type(TEXT("")), ::Wiz::Bool::False);
                        }
                        /// ID;
                        tDerivedPtr    MineID;
                        InArchive && (::Wiz::Byte::Ptr&)MineID;

                        MePtr->Serialize(InArchive);

                        if (this->m_ExternalSize > 0)
                        {
                            this->m_ExternalPtr = new ::Wiz::Byte::Type[this->m_ExternalSize];
                            if (::Wiz::IsValidPtr(this->m_ExternalPtr))
                            {
                                MePtr->SerializeExternal(InArchive);
                            }
                        }

                        m_Map.Insert(MineID, MePtr);
                    }

                    tMap::tIterator Itr = m_Map.Begin();
                    tMap::tIteratorConst ItrEnd = m_Map.End();

                    tMap::tIterator Temp;

                    for (; Itr != ItrEnd; Itr++)
                    {
                        tDerivedPtr ItrValue = Itr.GetValue(); 
                        if (::Wiz::NotNull(ItrValue->m_FirstChildPtr))
                        {
                            Temp = m_Map.Find(ItrValue->m_FirstChildPtr);
                            ItrValue->m_FirstChildPtr = Temp.GetValue();
                        }
                        if (::Wiz::NotNull(ItrValue->m_NextSiblingPtr))
                        {
                            Temp = m_Map.Find(ItrValue->m_NextSiblingPtr);
                            ItrValue->m_NextSiblingPtr = Temp.GetValue();
                        }
                        if (::Wiz::NotNull(ItrValue->m_ParentPtr))
                        {
                            Temp = m_Map.Find(ItrValue->m_ParentPtr);
                            ItrValue->m_ParentPtr = Temp.GetValue();
                        }
                    }

                    return ::Wiz::Bool::True;
                }

                ::Wiz::Bool::Type Write(::Wiz::Archive::InOut OutArchive)
                {
                    ::Wiz::UInt32::Type CurrPos = OutArchive.CurrPos();
                    ::Wiz::UInt32::Type UTest = 0;
                    OutArchive && UTest;
                    struct WriteFunc_t : public Type::ForEachFunc_t
                    {
                        ::Wiz::Archive::InOut       m_Archive;
                        ::Wiz::UInt32::Type         m_Count;
                        WriteFunc_t(::Wiz::Archive::InOut OB) : m_Archive(OB), m_Count(0)
                        {
                        }

                        virtual ::Wiz::Void::Type Do(tDerivedPtr InThisPtr)
                        {
                            if (::Wiz::NotValidPtr(InThisPtr))
                            {
                                return;
                            }

                            /// ID
                            m_Archive && ((::Wiz::Byte::Ptr&)InThisPtr);

                            InThisPtr->Serialize(m_Archive);

                            if ((InThisPtr->m_ExternalSize > 0) && ::Wiz::IsValidPtr(InThisPtr->m_ExternalPtr))
                            {
                                InThisPtr->SerializeExternal(m_Archive);
                            };

                            m_Count++;
                        }
                    };

                    WriteFunc_t WF(OutArchive);
                    ForEach(WF);

                    OutArchive.MoveTo(CurrPos);

                    OutArchive && WF.m_Count;
                    return ::Wiz::Bool::True;
                }
                //////////////////////////////////////////////////////////////////////////
            public:
                Type(::Wiz::UTF8::String::In InName, ::Wiz::Bool::In InIsFile) :
                    tSuper(InName, InIsFile), m_ExternalPtr(WIZ_NULLPTR), m_ExternalSize(0)
                {
                }
                Type() : tSuper(), m_ExternalPtr(WIZ_NULLPTR), m_ExternalSize(0)
                {
                }
            public:
                ::Wiz::Void::Ptr        m_ExternalPtr;
                ::Wiz::USize32::Type    m_ExternalSize;
            };
        } /// end of namespace DirTree
    } /// end of namespace VFS
} /// end of namespace Wiz

#endif /*__WIZ_VFS_DIRTREE_HPP__SHANHAOBO_19800429__*/
